From 541ae21b0b3bfb8f64768108182976e56f0827ff Mon Sep 17 00:00:00 2001 From: tsteven4 <13596209+tsteven4@users.noreply.github.com> Date: Mon, 13 Dec 2021 09:27:55 -0700 Subject: [PATCH] retire some csv char based routines. (#790) * retire some csv char based routines. The last csv_lineparse user, garmin_txt, is converted to csv_linesplit. xcsv_parse_val converted to use csv_stringtrim(QString,QString,int), eliminating the other overloads. xcsv_parse_style_line parsing of FIELD_DELIMITER, FIELD_ENCLOSER, RECORD_DELIMITER and BADCHARS updated to use the above overload of csv_stringtrim. FIELD_DELIMITER, FIELD_ENCLOSER and RECORD_DELIMITER changed to trim, with a double quote enclosure, before character substitution. There was a subtle bug in csvs_stringtrim(char, char, int). When trimming a source that was all white space the first white space character would be retained, while others would be trimmed. This did occur with CRNEWLINE, but the bug allowed other substitutions to work, e.g. SPACE, NEWLINE, TAB, CR. A small bug in csv_stringclean was fixed. If the to_nuke was empty an invalid regular expression was created. * save a few string conversions. * and a few more conversions saved. * review comments incorporated in garmin_txt reader. * fix minor bug accumulating badchars. --- csv_util.cc | 198 ++----------------------------------------- csv_util.h | 6 -- garmin_txt.cc | 229 ++++++++++++++++++++++++-------------------------- xcsv.cc | 66 +++++++-------- xcsv.h | 2 +- 5 files changed, 152 insertions(+), 349 deletions(-) diff --git a/csv_util.cc b/csv_util.cc index 0a5d986cc..f522bee69 100644 --- a/csv_util.cc +++ b/csv_util.cc @@ -52,80 +52,15 @@ QString csv_stringclean(const QString& source, const QString& to_nuke) { QString r = source; - // avoid problematic regular rexpressions, e.g. xmapwpt generated [:\n:], - // or one can imagine [0-9] when we meant the characters, '0', '-', and '9', - // or one can imagine [^a] when we meant the characters '^' and 'a'. - QRegularExpression regex = QRegularExpression(QString("[%1]").arg(QRegularExpression::escape(to_nuke))); - assert(regex.isValid()); - return r.remove(regex); -} - -// csv_stringtrim() - trim whitespace and leading and trailing -// enclosures (quotes) -// returns a copy of the modified string -// usage: p = csv_stringtrim(string, "\"", 0) -char* -csv_stringtrim(const char* string, const char* enclosure, int strip_max) -{ - static const char* p1 = nullptr; - char* tmp = xstrdup(string); - size_t elen; - - if (!strlen(string)) { - return (tmp); - } - - if (!enclosure) { - elen = 0; - } else { - elen = strlen(enclosure); - } - - char* p2 = tmp + strlen(tmp) - 1; - p1 = tmp; - - /* trim off trailing whitespace */ - while ((p2 > p1) && isspace(*p2)) { - p2--; - } - - /* advance p1 past any leading whitespace */ - while ((p1 < p2) && (isspace(*p1))) { - p1++; - } - - /* if no maximum strippage, assign a reasonable value to max */ - strip_max = strip_max ? strip_max : 9999; - - /* if we have enclosures, skip past them in pairs */ - if (elen) { - int stripped = 0; - while ( - (stripped < strip_max) && - ((size_t)(p2 - p1 + 1) >= (elen * 2)) && - (strncmp(p1, enclosure, elen) == 0) && - (strncmp((p2 - elen + 1), enclosure, elen) == 0)) { - p2 -= elen; - p1 += elen; - stripped++; - } - } - - /* copy what's left over back into tmp. */ - memmove(tmp, p1, (p2 - p1) + 1); - - tmp[(p2 - p1) + 1] = '\0'; - - return (tmp); -} - -// Is this really the replacement for the above? No. -QString -csv_stringtrim(const QString& source, const QString& enclosure) -{ - QString r = source; - r.replace(enclosure, ""); - return r.trimmed(); + if (!to_nuke.isEmpty()) { + // avoid problematic regular rexpressions, e.g. xmapwpt generated [:\n:], + // or one can imagine [0-9] when we meant the characters, '0', '-', and '9', + // or one can imagine [^a] when we meant the characters '^' and 'a'. + QRegularExpression regex = QRegularExpression(QString("[%1]").arg(QRegularExpression::escape(to_nuke))); + assert(regex.isValid()); + r.remove(regex); + } + return r; } // csv_stringtrim() - trim whitespace and leading and trailing @@ -212,121 +147,6 @@ csv_dequote(const QString& string, const QString& enclosure) return retval; } -/*****************************************************************************/ -/* csv_lineparse() - extract data fields from a delimited string. designed */ -/* to handle quoted and delimited data within quotes. */ -/* returns temporary COPY of delimited data field (use it */ -/* or lose it on the next call). */ -/* usage: p = csv_lineparse(string, ",", "\"", line) [initial call] */ -/* p = csv_lineparse(NULL, ",", "\"", line) [subsequent calls] */ -/*****************************************************************************/ -char* -csv_lineparse(const char* stringstart, const char* delimited_by, - const char* enclosed_in, const int line_no) -{ - static const char* p = nullptr; - static char* tmp = nullptr; - size_t dlen = 0, elen = 0, efound = 0; - int enclosedepth = 0; - short int hyper_whitespace_delimiter = 0; - - if (tmp) { - xfree(tmp); - tmp = nullptr; - } - - if (strcmp(delimited_by, "\\w") == 0) { - hyper_whitespace_delimiter = 1; - } - - /* - * This is tacky. Our "csv" format is actually "commaspace" format. - * Changing that causes unwanted churn, but it also makes "real" - * comma separated data (such as likely to be produced by Excel, etc.) - * unreadable. So we silently change it here on a read and let the - * whitespace eater consume the space. - */ - if (strcmp(delimited_by, ", ") == 0) { - delimited_by = ","; - } - - if (!p) { - /* first pass thru */ - p = stringstart; - - if (!p) { - /* last pass out */ - return (nullptr); - } - } - - /* the beginning of the string we start with (this pass) */ - const char* sp = p; - - /* length of delimiters and enclosures */ - if ((delimited_by) && (!hyper_whitespace_delimiter)) { - dlen = strlen(delimited_by); - } - if (enclosed_in) { - elen = strlen(enclosed_in); - } - short int dfound = 0; - - while ((*p) && (!dfound)) { - if ((elen) && (strncmp(p, enclosed_in, elen) == 0)) { - efound = 1; - p+=elen; - if (enclosedepth) { - enclosedepth--; - } else { - enclosedepth++; - } - continue; - } - - if (!enclosedepth) { - if ((dlen) && (strncmp(p, delimited_by, dlen) == 0)) { - dfound = 1; - } else if ((hyper_whitespace_delimiter) && (ISWHITESPACE(*p))) { - dfound = 1; - while (ISWHITESPACE(*p)) { - p++; - } - } else { - p++; - } - } else { - p++; - } - } - - /* allocate enough space for this data field */ - tmp = (char*) xcalloc((p - sp) + 1, sizeof(char)); - - strncpy(tmp, sp, (p - sp)); - tmp[p - sp] = '\0'; - - if (elen && efound) { - char* c = csv_stringtrim(tmp, enclosed_in, 0); - xfree(tmp); - tmp = c; - } - - if (dfound) { - /* skip over the delimited_by */ - p += dlen; - } else { - /* end of the line */ - p = nullptr; - } - - if (enclosedepth != 0) { - warning(MYNAME - ": Warning- Unbalanced Field Enclosures (%s) on line %d\n", - enclosed_in, line_no); - } - return (tmp); -} /*****************************************************************************/ /* csv_linesplit() - extract data fields from a delimited string. designed */ diff --git a/csv_util.h b/csv_util.h index 4ea9fa0be..c0461bb24 100644 --- a/csv_util.h +++ b/csv_util.h @@ -32,10 +32,6 @@ QString csv_stringclean(const QString& source, const QString& to_nuke); -char* -csv_stringtrim(const char* string, const char* enclosure, int strip_max); -QString -csv_stringtrim(const QString& source, const QString& enclosure); QString csv_stringtrim(const QString& string, const QString& enclosure, int strip_max); QString @@ -45,8 +41,6 @@ csv_dequote(const QString& string, const QString& enclosure); enum class CsvQuoteMethod {historic, rfc4180}; -char* -csv_lineparse(const char* stringstart, const char* delimited_by, const char* enclosed_in, int line_no); QStringList csv_linesplit(const QString& string, const QString& delimited_by, const QString& enclosed_in, const int line_no, CsvQuoteMethod method = CsvQuoteMethod::historic); diff --git a/garmin_txt.cc b/garmin_txt.cc index f49984112..d6a71236a 100644 --- a/garmin_txt.cc +++ b/garmin_txt.cc @@ -35,12 +35,14 @@ #include // for QChar, QChar::Other_Control #include // for QIODevice, QIODevice::ReadOnly, QIODevice::WriteOnly #include // for QString, operator!= +#include // for QStringList #include // for QTextStream #include // for QVector #include // for CaseInsensitive #include // for qPrintable -#include "csv_util.h" // for csv_lineparse +#include "csv_util.h" // for csv_linesplit +#include "formspec.h" // for FormatSpecificDataList #include "garmin_fs.h" // for garmin_fs_t, garmin_fs_alloc, garmin_fs_convert_category, GMSD_SECTION_CATEGORIES #include "garmin_tables.h" // for gt_display_modes_e, gt_find_desc_from_icon_number, gt_find_icon_number_from_desc, gt_get_mps_grid_longname, gt_lookup_datum_index, gt_lookup_grid_type, GDB, gt_get_icao_cc, gt_get_icao_country, gt_get_mps_datum_name, gt_waypt_class_names, GT_DISPLAY_MODE... #include "inifile.h" // for inifile_readstr @@ -123,7 +125,6 @@ static int header_ct[unknown_header + 1]; /* macros */ #define IS_VALID_ALT(a) (((a) != unknown_alt) && ((a) < GARMIN_UNKNOWN_ALT)) -#define DUPSTR(a) (((a) != NULL) && ((a)[0] != 0)) ? ((a)) : NULL static char* opt_datum = nullptr; static char* opt_dist = nullptr; @@ -883,76 +884,63 @@ free_header(const header_type ht) /* data parsers */ -static int -parse_date_and_time(char* str, time_t* value) +static bool +parse_date_and_time(const QString& str, time_t* value) { struct tm tm; memset(&tm, 0, sizeof(tm)); - char* cin = lrtrim(str); - if (*cin == '\0') { - return 0; + QString tstr = str.trimmed(); + if (tstr.isEmpty()) { + return false; } + const QByteArray ba = tstr.toUtf8(); + const char* cin = ba.constData(); char* cerr = strptime(cin, date_time_format, &tm); if (cerr == nullptr) { cerr = strptime(cin, "%m/%d/%Y %I:%M:%S %p", &tm); - is_fatal(cerr == nullptr, MYNAME ": Invalid date or/and time \"%s\" at line %d!", cin, current_line); + is_fatal(cerr == nullptr, MYNAME ": Invalid date or/and time \"%s\" at line %d!", qPrintable(tstr), current_line); } // printf(MYNAME "_parse_date_and_time: %02d.%02d.%04d, %02d:%02d:%02d\n", // tm.tm_mday, tm.tm_mon+1, tm.tm_year+1900, tm.tm_hour, tm.tm_min, tm.tm_sec); *value = mklocaltime(&tm); - return 1; + return true; } static uint16_t -parse_categories(const char* str) +parse_categories(const QString& str) { - char buff[256]; - uint16_t val; uint16_t res = 0; - char* cx; - - if (*str == '\0') { - return 0; - } - - strncpy(buff, str, sizeof(buff)); - char* cin = lrtrim(buff); - if (*cin == '\0') { - return 0; - } - - strcat(cin, ","); - while ((cx = strchr(cin, ','))) { - *cx++ = '\0'; - cin = lrtrim(cin); - if (*cin != '\0') { - if (!garmin_fs_convert_category(cin, &val)) { - warning(MYNAME ": Unable to convert category \"%s\" at line %d!\n", cin, current_line); + const QStringList catstrings = str.split(','); + for (const auto& catstring : catstrings) { + QString cin = catstring.trimmed(); + if (!cin.isEmpty()) { + uint16_t val; + if (!garmin_fs_convert_category(CSTR(cin), &val)) { + warning(MYNAME ": Unable to convert category \"%s\" at line %d!\n", qPrintable(cin), current_line); } else { res = res | val; } } - cin = cx; } return res; } -static int -parse_temperature(const char* str, double* temperature) +static bool +parse_temperature(const QString& str, double* temperature) { double value; unsigned char unit; - if ((str == nullptr) || (*str == '\0')) { - return 0; + if (str.isEmpty()) { + return false; } - if (sscanf(str, "%lf %c", &value, &unit) == 2) { + if (sscanf(CSTR(str), "%lf %c", &value, &unit) == 2) { unit = toupper(unit); switch (unit) { case 'C': @@ -964,22 +952,22 @@ parse_temperature(const char* str, double* temperature) default: fatal(MYNAME ": Unknown temperature unit \"%c\" at line %d!\n", unit, current_line); } - return 1; + return true; } else { - fatal(MYNAME ": Invalid temperature \"%s\" at line %d!\n", str, current_line); + fatal(MYNAME ": Invalid temperature \"%s\" at line %d!\n", qPrintable(str), current_line); } - return 0; + return false; } static void -parse_header() +parse_header(const QStringList& lineparts) { - char* str; int column = -1; free_header(unknown_header); - while ((str = csv_lineparse(nullptr, "\t", "", column++))) { + for (const auto& str : lineparts) { + column++; header_lines[unknown_header][column] = strupper(xstrdup(str)); header_ct[unknown_header]++; if (header_ct[unknown_header] >= MAX_HEADER_FIELDS) { @@ -988,21 +976,21 @@ parse_header() } } -static int -parse_display(const char* str, int* val) +static bool +parse_display(const QString& str, int* val) { - if ((str == nullptr) || (*str == '\0')) { - return 0; + if (str.isEmpty()) { + return false; } for (gt_display_modes_e i = GT_DISPLAY_MODE_MIN; i <= GT_DISPLAY_MODE_MAX; ++i) { if (case_ignore_strcmp(str, gt_display_mode_names[i]) == 0) { *val = i; - return 1; + return true; } } - warning(MYNAME ": Unknown display mode \"%s\" at line %d.\n", str, current_line); - return 0; + warning(MYNAME ": Unknown display mode \"%s\" at line %d.\n", qPrintable(str), current_line); + return false; } static void @@ -1049,41 +1037,39 @@ bind_fields(const header_type ht) } static void -parse_grid() +parse_grid(const QStringList& lineparts) { - char* str = csv_lineparse(nullptr, "\t", "", 1); - - if (str != nullptr) { - if (strstr(str, "dd.ddddd") != nullptr) { - grid_index = grid_lat_lon_ddd; - } else if (strstr(str, "mm.mmm") != nullptr) { - grid_index = grid_lat_lon_dmm; - } else if (strstr(str, "mm'ss.s") != nullptr) { - grid_index = grid_lat_lon_dms; - } else { - grid_index = gt_lookup_grid_type(str, MYNAME); - } - } else { + if (lineparts.size() < 1) { fatal(MYNAME ": Missing grid headline!\n"); } + + const QByteArray ba = lineparts.at(0).toUtf8(); + const char* str = ba.constData(); + if (strstr(str, "dd.ddddd") != nullptr) { + grid_index = grid_lat_lon_ddd; + } else if (strstr(str, "mm.mmm") != nullptr) { + grid_index = grid_lat_lon_dmm; + } else if (strstr(str, "mm'ss.s") != nullptr) { + grid_index = grid_lat_lon_dms; + } else { + grid_index = gt_lookup_grid_type(str, MYNAME); + } } static void -parse_datum() +parse_datum(const QStringList& lineparts) { - char* str = csv_lineparse(nullptr, "\t", "", 1); - - if (str != nullptr) { - datum_index = gt_lookup_datum_index(str, MYNAME); - } else { + if (lineparts.size() < 1) { fatal(MYNAME ": Missing GPS datum headline!\n"); } + + const auto& str = lineparts.at(0); + datum_index = gt_lookup_datum_index(CSTR(str), MYNAME); } static void -parse_waypoint() +parse_waypoint(const QStringList& lineparts) { - char* str; int column = -1; bind_fields(waypt_header); @@ -1092,17 +1078,22 @@ parse_waypoint() garmin_fs_t* gmsd = garmin_fs_alloc(-1); wpt->fs.FsChainAdd(gmsd); - while ((str = csv_lineparse(nullptr, "\t", "", column++))) { + for (const auto& str : lineparts) { + column++; int i; double d; int field_no = header_fields[waypt_header][column]; switch (field_no) { case 1: - wpt->shortname = DUPSTR(str); + if (!str.isEmpty()) { + wpt->shortname = str; + } break; case 2: - wpt->notes = DUPSTR(str); + if (!str.isEmpty()) { + wpt->notes = str; + } break; case 3: for (i = 0; i <= gt_waypt_class_map_line; i++) { @@ -1183,19 +1174,21 @@ parse_waypoint() } static void -parse_route_header() +parse_route_header(const QStringList& lineparts) { - char* str; int column = -1; auto* rte = new route_head; bind_fields(route_header); - while ((str = csv_lineparse(nullptr, "\t", "", column++))) { + for (const auto& str : lineparts) { + column++; int field_no = header_fields[route_header][column]; switch (field_no) { case 1: - rte->rte_name = DUPSTR(str); + if (!str.isEmpty()) { + rte->rte_name = str; + } break; case 5: rte->rte_urls.AddUrlLink(UrlLink(str)); @@ -1207,18 +1200,20 @@ parse_route_header() } static void -parse_track_header() +parse_track_header(const QStringList& lineparts) { - char* str; int column = -1; bind_fields(track_header); auto* trk = new route_head; - while ((str = csv_lineparse(nullptr, "\t", "", column++))) { + for (const auto& str : lineparts) { + column++; int field_no = header_fields[track_header][column]; switch (field_no) { case 1: - trk->rte_name = DUPSTR(str); + if (!str.isEmpty()) { + trk->rte_name = str; + } break; case 6: trk->rte_urls.AddUrlLink(UrlLink(str)); @@ -1230,21 +1225,21 @@ parse_track_header() } static void -parse_route_waypoint() +parse_route_waypoint(const QStringList& lineparts) { - char* str; int column = -1; Waypoint* wpt = nullptr; bind_fields(rtept_header); - while ((str = csv_lineparse(nullptr, "\t", "", column++))) { + for (const auto& str : lineparts) { + column++; int field_no = header_fields[rtept_header][column]; switch (field_no) { case 1: - is_fatal((*str == '\0'), MYNAME ": Route waypoint without name at line %d!\n", current_line); + is_fatal((str.isEmpty()), MYNAME ": Route waypoint without name at line %d!\n", current_line); wpt = find_waypt_by_name(str); - is_fatal((wpt == nullptr), MYNAME ": Route waypoint \"%s\" not in waypoint list (line %d)!\n", str, current_line); + is_fatal((wpt == nullptr), MYNAME ": Route waypoint \"%s\" not in waypoint list (line %d)!\n", qPrintable(str), current_line); wpt = new Waypoint(*wpt); break; } @@ -1255,18 +1250,18 @@ parse_route_waypoint() } static void -parse_track_waypoint() +parse_track_waypoint(const QStringList& lineparts) { - char* str; int column = -1; bind_fields(trkpt_header); auto* wpt = new Waypoint; - while ((str = csv_lineparse(nullptr, "\t", "", column++))) { + for (const auto& str : lineparts) { + column++; double x; - if (! *str) { + if (str.isEmpty()) { continue; } @@ -1304,7 +1299,7 @@ parse_track_waypoint() } break; case 9: - WAYPT_SET(wpt, course, atoi(str)); + WAYPT_SET(wpt, course, atoi(CSTR(str))); break; } } @@ -1354,37 +1349,35 @@ garmin_txt_read() continue; } - /* bail back to a (utf-8) char string, this format isn't worth the conversion work */ - QByteArray utf8str = buff.toUtf8(); - char* cin = csv_lineparse(utf8str.constData(), "\t", "", 0); + QStringList lineparts = csv_linesplit(buff, "\t", "", 0); - if (cin == nullptr) { + if (lineparts.size() < 1) { continue; } - - if (case_ignore_strcmp(cin, "Header") == 0) { - parse_header(); - } else if (case_ignore_strcmp(cin, "Grid") == 0) { - parse_grid(); - } else if (case_ignore_strcmp(cin, "Datum") == 0) { - parse_datum(); - } else if (case_ignore_strcmp(cin, "Waypoint") == 0) { - parse_waypoint(); - } else if (case_ignore_strcmp(cin, "Route Waypoint") == 0) { - parse_route_waypoint(); - } else if (case_ignore_strcmp(cin, "Trackpoint") == 0) { - parse_track_waypoint(); - } else if (case_ignore_strcmp(cin, "Route") == 0) { - parse_route_header(); - } else if (case_ignore_strcmp(cin, "Track") == 0) { - parse_track_header(); - } else if (case_ignore_strcmp(cin, "Map") == 0) /* do nothing */ ; + auto linetype = lineparts.at(0); + lineparts.removeFirst(); + + if (case_ignore_strcmp(linetype, "Header") == 0) { + parse_header(lineparts); + } else if (case_ignore_strcmp(linetype, "Grid") == 0) { + parse_grid(lineparts); + } else if (case_ignore_strcmp(linetype, "Datum") == 0) { + parse_datum(lineparts); + } else if (case_ignore_strcmp(linetype, "Waypoint") == 0) { + parse_waypoint(lineparts); + } else if (case_ignore_strcmp(linetype, "Route Waypoint") == 0) { + parse_route_waypoint(lineparts); + } else if (case_ignore_strcmp(linetype, "Trackpoint") == 0) { + parse_track_waypoint(lineparts); + } else if (case_ignore_strcmp(linetype, "Route") == 0) { + parse_route_header(lineparts); + } else if (case_ignore_strcmp(linetype, "Track") == 0) { + parse_track_header(lineparts); + } else if (case_ignore_strcmp(linetype, "Map") == 0) /* do nothing */ ; else { - fatal(MYNAME ": Unknown identifier (%s) at line %d!\n", cin, current_line); + fatal(MYNAME ": Unknown identifier (%s) at line %d!\n", qPrintable(linetype), current_line); } - /* flush pending data */ - while (csv_lineparse(nullptr, "\t", "", 0)); } } diff --git a/xcsv.cc b/xcsv.cc index bd3886c0d..20e3ad665 100644 --- a/xcsv.cc +++ b/xcsv.cc @@ -245,7 +245,7 @@ XcsvStyle::xcsv_ofield_add(XcsvStyle* style, const QString& qkey, const QString& } QDateTime -XcsvFormat::yyyymmdd_to_time(const char* s) +XcsvFormat::yyyymmdd_to_time(const QString& s) { QDate d = QDate::fromString(s, "yyyyMMdd"); #if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0)) @@ -387,7 +387,7 @@ void XcsvFormat::xcsv_parse_val(const QString& value, Waypoint* wpt, const XcsvStyle::field_map& fmp, xcsv_parse_data* parse_data, const int line_no) { - const char* enclosure = ""; + QString enclosure = ""; geocache_data* gc_data = nullptr; if (fmp.printfc.isNull()) { @@ -416,13 +416,13 @@ XcsvFormat::xcsv_parse_val(const QString& value, Waypoint* wpt, const XcsvStyle: /* IGNORE -- Calculated Sequence # For Output*/ break; case XcsvStyle::XT_SHORTNAME: - wpt->shortname = csv_stringtrim(s, enclosure); + wpt->shortname = csv_stringtrim(value, enclosure, 0); break; case XcsvStyle::XT_DESCRIPTION: - wpt->description = csv_stringtrim(s, enclosure); + wpt->description = csv_stringtrim(value, enclosure, 0); break; case XcsvStyle::XT_NOTES: - wpt->notes = csv_stringtrim(s, ""); + wpt->notes = value.trimmed(); break; case XcsvStyle::XT_URL: if (!parse_data->link_) { @@ -617,7 +617,7 @@ XcsvFormat::xcsv_parse_val(const QString& value, Waypoint* wpt, const XcsvStyle: } break; case XcsvStyle::XT_YYYYMMDD_TIME: - wpt->SetCreationTime(yyyymmdd_to_time(s)); + wpt->SetCreationTime(yyyymmdd_to_time(value)); break; case XcsvStyle::XT_GMT_TIME: wpt->SetCreationTime(sscanftime(s, fmp.printfc.constData(), 1)); @@ -649,7 +649,7 @@ XcsvFormat::xcsv_parse_val(const QString& value, Waypoint* wpt, const XcsvStyle: } break; case XcsvStyle::XT_GEOCACHE_LAST_FOUND: - wpt->AllocGCData()->last_found = yyyymmdd_to_time(s); + wpt->AllocGCData()->last_found = yyyymmdd_to_time(value); break; /* GEOCACHING STUFF ***************************************************/ @@ -663,10 +663,10 @@ XcsvFormat::xcsv_parse_val(const QString& value, Waypoint* wpt, const XcsvStyle: break; case XcsvStyle::XT_GEOCACHE_TYPE: /* Geocache Type */ - wpt->AllocGCData()->type = gs_mktype(s); + wpt->AllocGCData()->type = gs_mktype(value); break; case XcsvStyle::XT_GEOCACHE_CONTAINER: - wpt->AllocGCData()->container = gs_mkcont(s); + wpt->AllocGCData()->container = gs_mkcont(value); break; case XcsvStyle::XT_GEOCACHE_HINT: wpt->AllocGCData()->hint = value.trimmed(); @@ -676,9 +676,9 @@ XcsvFormat::xcsv_parse_val(const QString& value, Waypoint* wpt, const XcsvStyle: break; case XcsvStyle::XT_GEOCACHE_ISAVAILABLE: gc_data = wpt->AllocGCData(); - if (case_ignore_strcmp(csv_stringtrim(s, ""), "False") == 0) { + if (case_ignore_strcmp(value.trimmed(), "False") == 0) { gc_data->is_available = status_false; - } else if (case_ignore_strcmp(csv_stringtrim(s, ""), "True") == 0) { + } else if (case_ignore_strcmp(value.trimmed(), "True") == 0) { gc_data->is_available = status_true; } else { gc_data->is_available = status_unknown; @@ -686,9 +686,9 @@ XcsvFormat::xcsv_parse_val(const QString& value, Waypoint* wpt, const XcsvStyle: break; case XcsvStyle::XT_GEOCACHE_ISARCHIVED: gc_data = wpt->AllocGCData(); - if (case_ignore_strcmp(csv_stringtrim(s, ""), "False") == 0) { + if (case_ignore_strcmp(value.trimmed(), "False") == 0) { gc_data->is_archived = status_false; - } else if (case_ignore_strcmp(csv_stringtrim(s, ""), "True") == 0) { + } else if (case_ignore_strcmp(value.trimmed(), "True") == 0) { gc_data->is_archived = status_true; } else { gc_data->is_archived = status_unknown; @@ -711,11 +711,11 @@ XcsvFormat::xcsv_parse_val(const QString& value, Waypoint* wpt, const XcsvStyle: case XcsvStyle::XT_GPS_FIX: wpt->fix = (fix_type)(atoi(s)-(fix_type)1); if (wpt->fix < fix_2d) { - if (!case_ignore_strcmp(s, "none")) { + if (!case_ignore_strcmp(value, "none")) { wpt->fix = fix_none; - } else if (!case_ignore_strcmp(s, "dgps")) { + } else if (!case_ignore_strcmp(value, "dgps")) { wpt->fix = fix_dgps; - } else if (!case_ignore_strcmp(s, "pps")) { + } else if (!case_ignore_strcmp(value, "pps")) { wpt->fix = fix_pps; } else { wpt->fix = fix_unknown; @@ -724,13 +724,13 @@ XcsvFormat::xcsv_parse_val(const QString& value, Waypoint* wpt, const XcsvStyle: break; /* Tracks and routes *********************************************/ case XcsvStyle::XT_ROUTE_NAME: - parse_data->rte_name = csv_stringtrim(s, enclosure); + parse_data->rte_name = csv_stringtrim(value, enclosure, 0); break; case XcsvStyle::XT_TRACK_NEW: parse_data->new_track = atoi(s); break; case XcsvStyle::XT_TRACK_NAME: - parse_data->trk_name = csv_stringtrim(s, enclosure); + parse_data->trk_name = csv_stringtrim(value, enclosure, 0); break; /* OTHER STUFF ***************************************************/ @@ -1667,34 +1667,31 @@ XcsvStyle::xcsv_parse_style_line(XcsvStyle* style, QString line) const QStringList tokens = tokenstr.split(','); if (op == u"FIELD_DELIMITER") { - auto cp = xcsv_get_char_from_constant_table(tokens[0]); + auto sp = csv_stringtrim(tokenstr, "\"", 1); + auto cp = xcsv_get_char_from_constant_table(sp); style->field_delimiter = cp; - char* p = csv_stringtrim(CSTR(style->field_delimiter), " ", 0); /* field delimiters are always bad characters */ - if (0 == strcmp(p, "\\w")) { - style->badchars = " \n\r"; + if (cp == u"\\w") { + style->badchars += " \n\r"; } else { - style->badchars += p; + style->badchars += cp; } - xfree(p); } else if (op == u"FIELD_ENCLOSER") { - auto cp = xcsv_get_char_from_constant_table(tokens[0]); + auto sp = csv_stringtrim(tokenstr, "\"", 1); + auto cp = xcsv_get_char_from_constant_table(sp); style->field_encloser = cp; - char* p = csv_stringtrim(CSTR(style->field_encloser), " ", 0); - style->badchars += p; - xfree(p); + style->badchars += cp; } else if (op == u"RECORD_DELIMITER") { - auto cp = xcsv_get_char_from_constant_table(tokens[0]); + auto sp = csv_stringtrim(tokenstr, "\"", 1); + auto cp = xcsv_get_char_from_constant_table(sp); style->record_delimiter = cp; // Record delimiters are always bad characters. - auto* p = csv_stringtrim(CSTR(style->record_delimiter), " ", 0); - style->badchars += p; - xfree(p); + style->badchars += cp; } else if (op == u"FORMAT_TYPE") { if (tokens[0] == u"INTERNAL") { @@ -1718,10 +1715,9 @@ XcsvStyle::xcsv_parse_style_line(XcsvStyle* style, QString line) style->whitespace_ok = tokens[0].toInt(); } else if (op == u"BADCHARS") { - char* sp = csv_stringtrim(CSTR(tokenstr), "\"", 1); - QString cp = xcsv_get_char_from_constant_table(sp); + auto sp = csv_stringtrim(tokenstr, "\"", 1); + auto cp = xcsv_get_char_from_constant_table(sp); style->badchars += cp; - xfree(sp); } else if (op =="PROLOGUE") { style->prologue.append(tokenstr); diff --git a/xcsv.h b/xcsv.h index 56acc4cd2..4987b4265 100644 --- a/xcsv.h +++ b/xcsv.h @@ -370,7 +370,7 @@ private: /* Member Functions */ - static QDateTime yyyymmdd_to_time(const char* s); + static QDateTime yyyymmdd_to_time(const QString& s); static time_t sscanftime(const char* s, const char* format, int gmt); static time_t addhms(const char* s, const char* format); static QString writetime(const char* format, time_t t, bool gmt); -- 2.30.2